home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 1992 August / info-mac-1992.iso / Applications (app) / DaliClock / Clock.asm < prev    next >
Assembly Source File  |  1987-02-23  |  15KB  |  614 lines

  1.  
  2. ; This is Steve Capp's clock program, written in the early days of Macintosh.
  3.  
  4. ; The original program had every kind of display dependency: base address,
  5. ; rowbytes, and bounds.  As an added bonus, the code segment was self-
  6. ; modifying.  (The _code_ wasn't self-modifying, but the code segment had
  7. ; an embedded variable area.)  I disassembled it with MacNosy, fixed all(?)
  8. ; the compatibility bugs, threw in a few optimizations, and here it is.
  9. ; Somewhere along the way, I lost most of it: the code size (bytes in the
  10. ; CODE 1 resource) dropped from 3478 bytes to less than 1100.
  11.  
  12. ; I've cleared out most of the "magic numbers" from the code, but I still
  13. ; don't understand how the drawing works.  Good luck.
  14.  
  15. ; Tested on a Mac Plus and a MegaScreen.
  16.  
  17. ; Ephraim Vishniac
  18. ; February 22, 1987
  19. ;     uucp:    decvax!wanginst!wang!ephraim
  20. ; MCI mail:    masstech
  21. ; US snail:    P.O. Box 1357
  22. ;        East Arlington, MA 02174
  23.  
  24. ; Miscellaneous things I discovered:
  25. ;    When the mouse is below row 280 on the screen, an informative
  26. ;    message is displayed.  In this version, the string displayed
  27. ;    depends on the the mouse column (horizontal coordinate) reduced
  28. ;    modulo the number of strings.
  29. ;
  30. ;    Pressing the mouse while the cursor is above row 280 causes the
  31. ;    date to be displayed instead of the time.  Pressing the mouse
  32. ;    while the cursor is below row 280 exits to the shell.
  33. ;
  34. ;    To prevent screen burn-in, the digits move down and up through
  35. ;    a range of 75 rows.  The rate of motion is one row every sixteen
  36. ;    seconds.
  37.  
  38.     Include Traps.D        ; Use System and ToolBox traps
  39.     Include SysEquX.D    ; Use System equates
  40.     Include    ToolEqu.D    ; Use ToolBox equates
  41.     Include    QuickEquX.D    ; Use QuickDraw equates
  42.  
  43. ;    Some equates
  44.  
  45. qdGlobals    equ    -4        ; qdGlobals are at -4(A5)
  46.  
  47. NumNum        equ    6        ; six numerals
  48. NumWidth    equ    8        ; numeral is eight bytes wide (64 pixels)
  49. DispWidth    equ    NumNum*NumWidth    ; width of display area (bytes)
  50. DispRows    equ    72        ; display is 72 rows high
  51. DispBytes    equ    DispWidth*DispRows
  52. Steps        equ    9        ; Nine steps in transformation
  53. WorkBytes    equ    DispBytes*Steps    ; size of work area 
  54.  
  55. StringBase    equ    1000        ; first 'STR ' resource
  56. NumStrings    equ    4        ; number of 'STR ' resources
  57.  
  58. StartRow    equ    60        ; initial row for clock
  59. CursorBound    equ    280        ; cursor transition is at row 280
  60. MessageRow    equ    CursorBound+30    ; Starting row for announcements
  61.  
  62. ;    Globals
  63.  
  64.  
  65. MouseRow    ds.w    1        ; MousePoint.v
  66. MouseCol    ds.w    1        ; MousePoint.h
  67. ShowDate    ds.b    1        ; 0 = Show Time, 1 = Show Date
  68. LowCursor    ds.b    1        ; cursor is low on screen
  69.  
  70. Year        ds.w    1        ; This is a date-time record
  71. Month        ds.w    1        ; 
  72. Day        ds.w    1        ; 
  73. Hour        ds.w    1        ; 
  74. Minute        ds.w    1        ; 
  75. Second        ds.w    1        ; 
  76. WeekDay        ds.w    1        ; (not used by us, but set by _Secs2Date)
  77.  
  78. MyPort        ds.b    portRec        ; our GrafPort record
  79. MyBounds    equ    MyPort+portBits+bounds
  80. MyTopLeft    equ    MyBounds+topLeft
  81. MyTop        equ    MyTopLeft+v
  82. MyLeft        equ    MyTopLeft+h
  83. MyBotRight    equ    MyBounds+botRight
  84. MyBottom    equ    MyBotRight+v
  85. MyRight        equ    MyBotRight+h
  86. MyBaseAddr    equ    MyPort+portBits+baseAddr
  87. MyRowBytes    equ    MyPort+portBits+rowBytes
  88.  
  89. TrendDown    ds.b    1        ; 1 = Down, 0 = Up
  90.  
  91. PaintPtr    ds.l    1        ; screen address to start painting
  92.  
  93. OldData        ds.l    NumNum        ; previous date or time, expanded
  94. NewData        ds.l    NumNum        ; new date or time, expanded
  95.  
  96. WorkArea    ds.l    1        ; pointer to work area
  97.  
  98. glob39        ds.l    NumNum        ; pointers to mask resource (RAWB 20)
  99.  
  100. glob46        ds.l    10        ; pointers to numeral data (RAWB 1-10)
  101.  
  102. MyTempRect    ds.w    4        ; rectangle used in CHECKCUR
  103.  
  104. ;    Start here!
  105.  
  106. MAIN
  107.     JSR    INIT
  108.  
  109.     ; Calculate starting point for painting the screen
  110.     MOVEQ    #StartRow,D0        ; rows down from top
  111.     mulu    MyRowBytes(A5),D0    ; times bytes-per-row
  112.     ADD.L    MyBaseAddr(A5),D0    ; plus start of bitmap
  113.     move.w    MyRight(A5),D1        ; D1.W = right bound
  114.     sub.w    MyLeft(A5),D1        ; D1.W = screen width
  115.     sub.w    #DispWidth*8,D1        ; width of our drawing (pixels)
  116.     lsr.w    #4,D1            ; divide by two to center,
  117.     ext.l    D1            ;   and by eight for bytes
  118.     add.l    D1,D0            ; center the clock
  119.     MOVE.L    D0,PaintPtr(A5)
  120.  
  121.     ; Blackout!
  122.     _HideCursor            ; put the cursor away
  123.  
  124.     ; blacken the entire screen
  125.     PEA    MyBounds(A5)        ; rectangle for screen
  126.     PEA    qdGlobals+black(a5)    ; fill with black
  127.     _FillRect
  128.  
  129. ; One-time setup for main loop
  130.  
  131.     JSR    GetTime
  132.  
  133.     JSR    SetData
  134.  
  135.     Moveq    #NumNum-1,D0        ; copy NewData to OldData
  136.     LEA    NewData(A5),A0
  137.     LEA    OldData(A5),A1
  138. @1    MOVE.L    (A0)+,(A1)+
  139.     dbra    D0,@1
  140.  
  141.  
  142.     CLR.B    TrendDown(A5)        ; establish a trend
  143.     BRA    @2            ; hop into loop
  144.  
  145. ; This is the top of the main loop
  146.  
  147. @3    move.L    Time,D6            ; D6 = old time
  148.     JSR    MELT
  149.  
  150.     ; Wait for the second to change
  151. @4    cmp.L    Time,D6            ; compare old time to current time
  152.     beq    @4            ; loop until the seconds change
  153.     JSR    GetTime            ; and then get the full time
  154.  
  155.     JSR    SetData            ; convert time/date to data
  156.  
  157.     ; The following stuff moves the image up or down by one row
  158.     ; every sixteen seconds to avoid screen burn-in.
  159.  
  160. @6    MOVE.B    Time+3,D0        ; Get low order byte of time
  161.     and.b    #$F,D0            ; every 16 secs, shift
  162.     BNE    @9            ; branch if non-zero, don't shift
  163.  
  164.     MOVE.W    MyRowBytes(A5),D0
  165.     EXT.L    D0            ; D0.L = bytes per row
  166.     TST.B    TrendDown(A5)        ; Should we move up or down?
  167.     BEQ    @7            ; branch if up
  168.     ADD.L    D0,PaintPtr(A5)        ; move down one row
  169.     BRA    @8
  170. @7    SUB.L    D0,PaintPtr(A5)        ; move up one row
  171.  
  172. @8    DBRA    D7,@9            ; every once in a while, switch
  173. @2    MOVE.W    #DispRows+2,D7        ; recharge the trend counter
  174.     BCHG.B    #0,TrendDown(A5)    ; flip the trend flag
  175.  
  176. @9    JSR    CHECKCUR        ; check the mouse position
  177.  
  178.     PEA    glob46(A5)        ; pointers to numeral data
  179.     PEA    OldData(A5)        ; old time or date
  180.     PEA    NewData(A5)        ; new time or date
  181.     Move.L    WorkArea(A5),-(A7)    ; pointer to work area
  182.     PEA    glob39(A5)        ; offsets into mask resource
  183.     JSR    PROC30            ; build new images
  184.  
  185.     ; If Button, Show Date
  186.     ; If Not Button, Show Time
  187.     ; If LowCursor & Button, Fall out
  188.     CLR    -(A7)
  189.     _Button                ; (A7) = Button
  190.     MOVE.B    (A7),ShowDate(A5)    ; If button, Show Date
  191.  
  192.     MOVE.B    LowCursor(A5),D0
  193.     AND.B    (A7)+,D0        ; D0 = LowCursor & Button
  194.     BEQ    @3
  195.  
  196.     RTS                ; Exit to wherever we came from...
  197.  
  198.  
  199. StringPtr    set    8        ; single parameter for ANNOUNCE
  200.  
  201. ;-refs - CHECKCUR    
  202.  
  203. ANNOUNCE
  204.     LINK    A6,#-0
  205.  
  206.     move.w    #SrcBic,-(A7)
  207.     _TextMode
  208.  
  209.     CLR    -(A7)            ; for string width
  210.     MOVE.L StringPtr(A6),-(A7)    ; string pointer
  211.     _StringWidth            ; (A7) = string width
  212.  
  213.     move.w    MyRight(A5),D1        ; D1.W = right bound
  214.     sub.w    MyLeft(A5),D1        ; D1.W = screen width
  215.     SUB.W    (A7)+,D1        ; D1.W = excess screen width
  216.     LSR.W    #1,D1            ; D1 = half of excess screen width
  217.     move.w    D1,-(A7)
  218.     move.w    #MessageRow,-(A7)    ; row for drawing text
  219.     _MoveTo
  220.  
  221.     MOVE.L StringPtr(A6),-(A7)    ; string pointer
  222.     _DrawString
  223.  
  224.     UNLK    A6
  225.     Move.L    (A7)+,(A7)        ; remove parameter
  226.     RTS    
  227.  
  228.  
  229. ;-refs - MELT    MAIN    
  230.  
  231. CHECKCUR
  232.     PEA    MouseRow(A5)
  233.     _GetMouse
  234.     CMPI    #CursorBound,MouseRow(A5)
  235.     BLE    @4            ; branch if mouse in upper screen
  236.  
  237.     BSET.B    #0,LowCursor(A5)    ; mouse is low now
  238.     BNE    @3            ; skip if it was already
  239.  
  240.     _ShowCursor            ; else show cursor and message
  241.  
  242.     CLR.L    -(A7)            ; for string handle
  243.     move.w    MouseCol(A5),D0        ; Get mouse column
  244.     ext.l    D0
  245.     divu    #NumStrings,D0        ; equal chance of each message
  246.     swap    D0            ; D0.W = remainder
  247.     add.w    #StringBase,D0        ; D0.W = STR resource number
  248.     move.w    D0,-(A7)        ; string #
  249.     _GetString
  250.     move.L    (A7)+,A0        ; string handle
  251.     move.L    (A0),-(A7)        ; string pointer
  252.     JSR    ANNOUNCE
  253. @3    BRA    @5
  254.  
  255. @4    BCLR.B    #0,LowCursor(A5)    ; Mouse is high now
  256.     BEQ    @5            ; skip if it was already
  257.  
  258.     _HideCursor            ; else hide cursor and message
  259.  
  260.     LEA    MyTempRect(A5),A1    ; A1 = our rectangle
  261.     Move.L    A1,-(A7)        ; push for _FillRect
  262.     move.w    #CursorBound,(A1)+    ; top of rect
  263.     move.w    MyLeft(a5),(A1)+    ; left of screen
  264.     move.l    MyBotRight(a5),(A1)+    ; bottom right of screen
  265.     PEA    qdGlobals+black(a5)    ; fill with black
  266.     _FillRect
  267.  
  268. @5    RTS    
  269.  
  270.  
  271. ;-refs - MAIN    
  272.  
  273. INIT
  274.     ; Build array of pointers to RAWB 1-10
  275.     CLR    D7
  276.     LEA    glob46(A5),A3
  277. @1    ADDQ    #1,D7
  278.     CLR.L    -(A7)
  279.     move.L    #'RAWB',-(A7)
  280.     move.w    D7,-(A7)
  281.     _GetResource
  282.     move.L    (A7)+,A0
  283.     MOVE.L    (A0),(A3)+
  284.     CMPI    #9,D7
  285.     BLE    @1
  286.  
  287.     CLR.L    -(A7)
  288.     move.L    #'RAWB',-(A7)
  289.     move.w    #20,-(A7)
  290.     _GetResource
  291.     move.L    (A7)+,A0
  292.     MOVE.L    (A0),A4            ; RAWB 20 pointer
  293.     LEA    64(A4),A3
  294.     LEA    glob39(A5),A0        ; glob39[0]
  295.     MOVE.L    A3,(A0)+        ; glob39[0]
  296.     MOVE.L    A4,(A0)+        ; glob39[1]
  297.     MOVE.L    A3,(A0)+        ; glob39[2]
  298.     MOVE.L    A4,(A0)+        ; glob39[3]
  299.     MOVE.L    A3,(A0)+        ; glob39[4]
  300.     MOVE.L    A4,(A0)+        ; glob39[5]
  301.  
  302.     move.L    #WorkBytes,D0        ; space for building images
  303.     _NewPtr
  304.     move.L    A0,WorkArea(a5)        ; start of allocated memory
  305.  
  306.     CLR.B    LowCursor(A5)
  307.     CLR.B    ShowDate(A5)
  308.  
  309.     PEA    qdGlobals(A5)
  310.     _InitGraf
  311.  
  312.     PEA    MyPort(A5)
  313.     _OpenPort
  314.  
  315.     _InitCursor
  316.  
  317.     _InitFonts
  318.     move.w    #applFont,-(A7)        ; use application font
  319.     _TextFont
  320.     move.w    #18,-(A7)        ; in 18 point size
  321.     _TextSize
  322.  
  323.     RTS    
  324.  
  325.  
  326. MELTTICKS    equ    4        ; ticks to delay in MELT
  327.  
  328. ;-refs - MAIN    
  329.  
  330. MELT
  331.     MOVEM.L D6-D7/A4,-(A7)
  332.     moveq    #Steps-1,D7
  333.     Move.L    WorkArea(A5),A4        ; A4 = work area
  334.  
  335. @1    MOVE.L    #MELTTICKS,D6        ; D6 = ticks to delay
  336.     ADD.L    Ticks,D6        ; D6 = tick time to delay until
  337.  
  338.     move.L    A4,-(A7)        ; push pointer to painting area
  339.     TST.B    ShowDate(A5)        ; Show Date?
  340.     BEQ    @2            ; branch if not
  341.     JSR    PROC34            ; paint squares for showing date
  342.     BRA    @3
  343.  
  344. @2    JSR    PROC33            ; paint circles for showing time
  345.  
  346. @3    move.L    A4,-(A7)        ; push pointer into work area
  347.     move.L    PaintPtr(A5),-(A7)    ; push pointer to screen image
  348.     JSR    PROC31            ; copy image to screen
  349.  
  350. @4    IF    MELTTICKS>1
  351.     JSR    CHECKCUR
  352.     ENDIF
  353.  
  354.     CMP.L    Ticks,D6        ; Time to go on yet?
  355.     BGT    @4            ; Loop if not
  356.  
  357.     LEA    DispBytes(A4),A4    ; next image in work area
  358.     dbra    D7,@1
  359.  
  360.     moveq    #NumNum-1,D7
  361.     LEA    NewData(A5),A0
  362.     LEA    OldData(A5),A1
  363. @8    MOVE.L    (A0)+,(A1)+
  364.     DBRA    D7,@8
  365.  
  366.     MOVEM.L (A7)+,D6-D7/A4
  367.     RTS
  368.  
  369.  
  370. ;-refs - MAIN    
  371.  
  372. SetData
  373.     lea    Year(A5),A0        ; input area
  374.     TST.B    ShowDate(A5)        ; Show date?
  375.     bne    @1            ; skip if so    
  376.     lea    Hour(A5),A0        ; else show time
  377. @1    LEA    NewData(A5),A1        ; output area
  378.     moveq    #2,D1            ; 3 fields to process
  379. @0    move    (a0)+,D0        ; D0 = field to process
  380.     ext.l    D0            ; clear high word
  381.     divu    #10,D0            ; divide by ten
  382.     clr.w    (a1)+            ; clear high word of output
  383.     move.w    D0,(A1)+        ; set decades
  384.     swap    D0
  385.     clr.w    (A1)+            ; clear high word of output
  386.     move.w    D0,(A1)+        ; set units
  387.     dbra    D1,@0
  388.  
  389.     RTS
  390.  
  391.  
  392.  
  393. ;-refs - MAIN    
  394.  
  395. param1    set    76        ; numeral data (glob46)
  396. param2    set    72        ; old data (OldData)
  397. param3    set    68        ; new data (NewData)
  398. param4    set    64        ; work area (WorkArea)
  399. param5    set    60        ; mask table pointers (glob39)
  400. paramsize    set    20
  401.  
  402. PROC30
  403.     move.L    (A7)+,A0        ; A0 = return address
  404.     MOVEM.L D0-D7/A0-A6,-(A7)    ; sixty bytes onto stack
  405.     
  406.     Move.L    param4(A7),A5        ; A5 = start of work area
  407.     Lea    (NumNum-1)*NumWidth(A5),A3    ; offset to right-most digit
  408.  
  409.     MOVE    #20,D0            ; index to unit seconds or days
  410. @1    MOVEA.L param1(A7),A4        ; A4 = base of numeral data ptr array
  411.     MOVEA.L param2(A7),A5        ; old data
  412.     MOVE.L    0(A5,D0.W),D6        ; D6 = old digit
  413.     LSL    #2,D6
  414.     MOVEA.L 0(A4,D6.W),A1        ; A1 = data for old digit
  415.     MOVEA.L param3(A7),A5        ; new data
  416.     MOVE.L    0(A5,D0.W),D6        ; D6 = new digit
  417.     LSL    #2,D6
  418.     MOVEA.L 0(A4,D6.W),A2        ; A2 = data for new digit
  419.     MOVEA.L param5(A7),A5
  420.     MOVEA.L 0(A5,D0.W),A0        ; A0 = ptr to RAWB 20 (perhaps +64)
  421.  
  422.     MOVE    #DispRows-1,D1
  423. @2    MOVEA.L A3,A4
  424.     MOVE    (A1)+,D2
  425.     MOVE    (A1)+,D3
  426.     MOVE    (A2)+,D4
  427.     MOVE    (A2)+,D5
  428.     ADDI    #15,D5
  429.     SUB    D2,D4
  430.     ASR    #3,D4
  431.     SUB    D3,D5
  432.     ASR    #3,D5
  433.  
  434.     MOVEQ    #Steps-1,D7
  435. @3    MOVE    D2,D6
  436.     LSR    #1,D6
  437.     ANDI    #$FFF8,D6
  438.     MOVEA.L A0,A5
  439.     ADDA.W    D6,A5
  440.     MOVE    D3,D6
  441.     LSR    #1,D6
  442.     ANDI    #$FFF8,D6
  443.     MOVEA.L A0,A6
  444.     ADDA.W    D6,A6
  445.     MOVE.L    (A6)+,D6
  446.     NOT.L    D6
  447.     AND.L    (A5)+,D6
  448.     MOVE.L    D6,(A4)+
  449.     MOVE.L    (A6)+,D6
  450.     NOT.L    D6
  451.     AND.L    (A5)+,D6
  452.     MOVE.L    D6,(A4)+
  453.     ADD    D4,D2
  454.     ADD    D5,D3
  455.     ADDA.W    #DispBytes-NumWidth,A4    ; next image
  456.     DBRA    D7,@3
  457.  
  458.     MOVEA.L A3,A4
  459.     MOVE    (A1)+,D2
  460.     MOVE    (A1)+,D3
  461.     MOVE    (A2)+,D4
  462.     MOVE    (A2)+,D5
  463.     ADDI    #15,D5
  464.     SUB    D2,D4
  465.     ASR    #3,D4
  466.     SUB    D3,D5
  467.     ASR    #3,D5
  468.  
  469.     MOVEQ    #Steps-1,D7
  470. @4    MOVE    D2,D6
  471.     LSR    #1,D6
  472.     ANDI    #$FFF8,D6
  473.     MOVEA.L A0,A5
  474.     ADDA.W    D6,A5
  475.     MOVE    D3,D6
  476.     LSR    #1,D6
  477.     ANDI    #$FFF8,D6
  478.     MOVEA.L A0,A6
  479.     ADDA.W    D6,A6
  480.     MOVE.L    (A6)+,D6
  481.     NOT.L    D6
  482.     AND.L    (A5)+,D6
  483.     OR.L    D6,(A4)+
  484.     MOVE.L    (A6)+,D6
  485.     NOT.L    D6
  486.     AND.L    (A5)+,D6
  487.     OR.L    D6,(A4)+
  488.     ADD    D4,D2
  489.     ADD    D5,D3
  490.     ADDA.W    #DispBytes-NumWidth,A4    ; next image
  491.     DBRA    D7,@4
  492.  
  493.     ADDA.W    #DispWidth,A3        ; next row
  494.     DBRA    D1,@2
  495.  
  496.     SUB.W    #DispBytes+NumWidth,A3    ; back to top, previous numeral
  497.     SUBQ    #3,D0            ; previous numeral
  498.     DBMI    D0,@1
  499.  
  500.     MOVEM.L (A7)+,D0-D7/A0-A6    ; restore all registers
  501.     ADDA.W    #ParamSize,A7        ; clear parameters
  502.     JMP    (A0)
  503.  
  504.  
  505.  
  506. ;-refs - MELT    
  507.  
  508. PROC31
  509.     move.L    (A7)+,D0        ; D0 = return address
  510.     move.L    (A7)+,A0        ; A0 = place to draw
  511.     move.L    (A7)+,A1        ; A1 = stuff to draw
  512.     move.L    D0,-(A7)        ; restore return address
  513.  
  514.     MOVEQ    #DispRows-1,D0        ; rows in drawing
  515. @1    move.l    A0,-(A7)        ; save start of row
  516.     MOVEQ    #DispWidth/4-1,D1    ; width of drawing, in longs
  517. @2    NOT.L    (A1)
  518.     MOVE.L    (A1)+,(A0)+
  519.     DBRA    D1,@2
  520.  
  521.     move.l    (A7)+,A0        ; restore start of row
  522.     ADDA.W    MyRowBytes(A5),A0    ; skip to next row
  523.     DBRA    D0,@1
  524.  
  525.     RTS    
  526.  
  527. ; PROC33 paints the colons which separate portions of the time
  528. ;-refs - MELT    
  529.  
  530. Circle    dc.w    %0000001111000000
  531.     dc.w    %0000011111100000
  532.     dc.w    %0000111111110000
  533.     dc.w    %0000111111110000
  534.     dc.w    %0000111111110000
  535.     dc.w    %0000111111110000
  536.     dc.w    %0000011111100000
  537.     dc.w    %0000001111000000
  538.  
  539. PROC33
  540.     move.L    (A7)+,D0        ; D0 = return address
  541.     move.L    (A7)+,A0        ; A0 = place to paint
  542.     LEA    Circle,A1        ; A1 = Circle image
  543.  
  544.     ADDA.W    #22*DispWidth+2*NumWidth-1,A0
  545.                 ; 22 rows down, 2 chars in, back 8 pixels
  546.     MOVE    #7,D2
  547. @1    MOVE.B    (A1)+,D1        ; D1.B = byte of image
  548.     MOVE.B    D1,2*NumWidth(A0)    ; top right (2 chars over)
  549.     MOVE.B    D1,18*DispWidth(A0)    ; bottom left (18 rows down)
  550.     MOVE.B    D1,18*DispWidth+2*NumWidth(A0)    ; bottom right (18 down, 2 over)
  551.     MOVE.B    D1,(A0)+        ; top left
  552.  
  553.     MOVE.B    (A1)+,D1        ; D1.B = byte of image
  554.     MOVE.B    D1,2*NumWidth(A0)    ; top right (2 chars over)
  555.     MOVE.B    D1,18*DispWidth(A0)    ; bottom left (18 rows down)
  556.     MOVE.B    D1,18*DispWidth+2*NumWidth(A0)    ; bottom right (18 down, 2 over)
  557.     MOVE.B    D1,(A0)+        ; top left
  558.  
  559.     ADDA.W    #DispWidth-2,A0        ; next row
  560.     DBRA    D2,@1
  561.  
  562.     MOVEA.L D0,A0
  563.     JMP    (A0)
  564.  
  565.  
  566. ; PROC34 paints the squares which separate portions of the date
  567. ;-refs - MELT    
  568.  
  569. Square    dc.w    %0000000000000000    ; actually a rectangle
  570.     dc.w    %0000000000000000
  571.     dc.w    %0000111111110000
  572.     dc.w    %0000111111110000
  573.     dc.w    %0000111111110000
  574.     dc.w    %0000111111110000
  575.     dc.w    %0000111111110000
  576.     dc.w    %0000111111110000
  577.  
  578. PROC34
  579.     move.L    (A7)+,D0        ; D0 = return address
  580.     move.L    (A7)+,A0        ; A0 = place to paint
  581.     LEA    Square,A1        ; A1 = Square
  582.  
  583.     ADDA.W    #32*DispWidth+2*NumWidth-1,A0
  584.                 ; 32 rows down, 2 chars in, 8 pixels back
  585.     MOVE    #7,D2
  586. @1    MOVE.B    (A1)+,D1        ; D1.B = byte of square
  587.     MOVE.B    D1,2*NumWidth(A0)    ; right (2 chars right)
  588.     MOVE.B    D1,(A0)+        ; left
  589.  
  590.     MOVE.B    (A1)+,D1        ; D1.B = byte of square
  591.     MOVE.B    D1,2*NumWidth(A0)    ; right (2 chars right)
  592.     MOVE.B    D1,(A0)+        ; left
  593.  
  594.     ADDA.W    #DispWidth-2,A0        ; next row
  595.     DBRA    D2,@1
  596.  
  597.     MOVEA.L D0,A0
  598.     JMP    (A0)
  599.  
  600.  
  601.  
  602. ;-refs - MAIN    
  603.  
  604. GetTime
  605.     move.l    Time,D0
  606.     LEA    Year(A5),A0
  607.     _Secs2Date
  608.     Move.W    (A0),D0            ; D0 = year
  609.     Ext.L    D0            ; clear high word
  610.     Divu    #100,D0            ; divide by century
  611.     Swap    D0            ; D0.W = year within century
  612.     Move.W    D0,(A0)            ; set decade+year, no centuries
  613.     RTS    
  614.